package com.chenkaiwei.shirojwtintegrationdemo.config;

import com.chenkaiwei.shirojwtintegrationdemo.filter.CorsFilter;
import com.chenkaiwei.shirojwtintegrationdemo.filter.JwtFilter;
import com.chenkaiwei.shirojwtintegrationdemo.realms.TokenValidateAndAuthorizingRealm;
import com.chenkaiwei.shirojwtintegrationdemo.realms.UsernamePasswordRealm;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationListener;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.authz.Authorizer;
import org.apache.shiro.authz.ModularRealmAuthorizer;
import org.apache.shiro.event.support.EventListener;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Configuration
@Slf4j
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SessionsSecurityManager securityManager) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();


        //配置自定义filter
        Map<String, Filter> filterMap = new HashMap<>();
        filterMap.put("cors",new CorsFilter());
        filterMap.put("jwt", new JwtFilter());//定义filter
        factoryBean.setFilters(filterMap);

        /*
         * filter配置规则参考官网
         * http://shiro.apache.org/web.html#urls-
         * 默认过滤器对照表
         * https://shiro.apache.org/web.html#default-filters
         */
        Map<String, String> filterRuleMap = new HashMap<>();

        filterRuleMap.put("/static/*", "anon");
        filterRuleMap.put("/error", "anon");
        filterRuleMap.put("/register", "anon");
        filterRuleMap.put("/login", "anon");
        //↑配置不参与验证的映射路径。


        // 关键：jwt验证过滤器。
        //↓ 此处采用shiro1.6新增的默认过滤器：authcBearer-BearerHttpAuthenticationFilter。
//        filterRuleMap.put("/**", "authcBearer");
        filterRuleMap.put("/**", "jwt");

        //↑ 注意：如果有其他过滤法则要配在/**上，则使用逗号间隔。

        //  perms[actuator] 对应 PermissionsAuthorizationFilter
        factoryBean.setGlobalFilters(Arrays.asList("cors","noSessionCreation"));
        //↑ 这句非常关键：配置NoSessionCreationFilter，把整个项目变成无状态服务。
        //将corsFilter配置成全局，注意不能放在上面jwt的位置。只有放在这里才能不受"anon"等其他过滤器的影响，是真正的全局。

        factoryBean.setSecurityManager(securityManager);
        factoryBean.setFilterChainDefinitionMap(filterRuleMap);
        return factoryBean;
    }

    @Bean
    protected Authorizer authorizer() {
        ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer();


        return authorizer;
    }
}
